التعامل مع الدخل والخرج (I/O) وتنسيقه في لغة C
تمثل عمليات الدخل والخرج (Input/Output) أحد الجوانب الجوهرية والأساسية في أي لغة برمجة، إذ تسمح للبرامج بالتفاعل مع المستخدم ونظام التشغيل والأجهزة الطرفية. وفي لغة C، تتم معالجة هذه العمليات من خلال مكتبة قياسية تعرف بـ ، وهي اختصار لـ Standard Input/Output. تشمل هذه المكتبة مجموعة من الدوال التي تتيح التعامل مع البيانات المقروءة والمطبوعة، سواء كانت من وإلى الشاشة أو من وإلى الملفات.
المفهوم العام للدخل والخرج في لغة C
تشير عملية الدخل (Input) إلى استقبال البيانات من المستخدم أو مصدر خارجي (مثل لوحة المفاتيح أو ملف)، بينما تشير عملية الخرج (Output) إلى طباعة البيانات أو إرسالها إلى وسيلة إخراج مثل الشاشة أو ملف. توفر لغة C دعماً مباشراً ومرناً لهاتين العمليتين عبر دوال متنوعة، منها scanf() وprintf() للتعامل مع المستخدم، وfscanf() وfprintf() للتعامل مع الملفات، بالإضافة إلى دوال منخفضة المستوى مثل getchar() وputchar().
مكتبة stdio.h: الركيزة الأساسية للتعامل مع I/O
تعد مكتبة جزءاً من مكتبة C القياسية وتحتوي على التعاريف والتصريحات الأساسية التي تسمح بالوصول إلى دوال الإدخال والإخراج. تشمل هذه الدوال:
-
printf(): لعرض البيانات على الشاشة. -
scanf(): لقراءة البيانات من المستخدم. -
getchar()/putchar(): لقراءة أو طباعة حرف واحد. -
gets()/puts(): لقراءة أو طباعة سطر نصي (رغم أنgets()أصبحت غير موصى بها). -
fopen()/fclose(): لفتح وإغلاق الملفات. -
fread()/fwrite(): للقراءة والكتابة الثنائية من/إلى الملفات. -
fgetc()/fputc(): للتعامل مع الحروف من/إلى الملفات. -
fgets()/fputs(): للتعامل مع السطور من/إلى الملفات.
تنسيق الإخراج باستخدام printf()
تُعد دالة printf() من أشهر دوال الإخراج في لغة C، وتُستخدم لطباعة القيم على الشاشة بصيغ مختلفة. تعتمد هذه الدالة على سلسلة تنسيقية تحتوي على رموز خاصة تسمى “مواصفات التنسيق” (format specifiers) تُحدد كيفية عرض القيم.
أشهر مواصفات التنسيق:
| المواصفة | النوع | مثال |
|---|---|---|
%d |
عدد صحيح (int) | printf("%d", 10); |
%f |
عدد عشري (float) | printf("%f", 3.14); |
%c |
حرف (char) | printf("%c", 'A'); |
%s |
سلسلة نصية (string) | printf("%s", "Hello"); |
%x |
عدد بصيغة هكساديسيمال | printf("%x", 255); |
%o |
عدد بصيغة أوكتال | printf("%o", 10); |
%e |
عدد بصيغة علمية | printf("%e", 1000.0); |
يمكن تخصيص العرض عبر تحديد عرض الحقل، الدقة، والمحاذاة. على سبيل المثال:
cprintf("%10.2f", 3.14159); // يطبع العدد في حقل عرضه 10 مع دقتين عشريتين
تنسيق الإدخال باستخدام scanf()
تُستخدم دالة scanf() لقراءة القيم من المستخدم، وتعتمد في عملها أيضاً على مواصفات التنسيق، لكنها تختلف قليلاً في أنها تحتاج إلى تمرير عنوان المتغير باستخدام معامل العنوان & في معظم الحالات.
مثال:
cint idade;
float salario;
char nome[50];
scanf("%d", &idade);
scanf("%f", &salario);
scanf("%s", nome); // لا يحتاج & لأن الاسم يمثل مؤشراً بالفعل
عند استخدام scanf() يجب توخي الحذر من حيث التحقق من صحة البيانات المدخلة، لأن الاستخدام الخاطئ قد يؤدي إلى سلوك غير متوقع أو ثغرات أمنية.
التعامل مع الحروف والسلاسل النصية
توفر لغة C دعماً للحروف الفردية والسلاسل النصية. للتعامل مع الحروف، يمكن استخدام الدوال getchar() وputchar():
cchar ch;
ch = getchar(); // يقرأ حرفًا
putchar(ch); // يطبعه
أما السلاسل النصية، فيمكن قراءتها بواسطة scanf("%s", str) أو fgets(str, size, stdin) (الأكثر أماناً)، ويمكن طباعتها باستخدام printf() أو puts():
cchar nome[100];
fgets(nome, sizeof(nome), stdin);
puts(nome);
الإدخال والإخراج مع الملفات
التعامل مع الملفات في C يتطلب فتح الملف، إجراء العملية المطلوبة، ثم إغلاق الملف. ويبدأ ذلك باستخدام الدالة fopen() التي ترجع مؤشراً من نوع FILE *.
أنماط فتح الملفات:
| النمط | الوصف |
|---|---|
"r" |
قراءة من ملف موجود |
"w" |
كتابة إلى ملف (يُنشأ أو يُفرغ) |
"a" |
الإلحاق بملف (إن لم يوجد يُنشأ) |
"r+" |
قراءة وكتابة (يجب أن يوجد الملف) |
"w+" |
قراءة وكتابة (يُفرغ أو يُنشأ) |
"a+" |
قراءة وإلحاق |
مثال على كتابة وقراءة ملف:
cFILE *fp;
// كتابة إلى الملف
fp = fopen("dados.txt", "w");
if (fp != NULL) {
fprintf(fp, "Nome: %s\nIdade: %d", "Ali", 25);
fclose(fp);
}
// قراءة من الملف
char buffer[100];
fp = fopen("dados.txt", "r");
if (fp != NULL) {
while (fgets(buffer, sizeof(buffer), fp)) {
printf("%s", buffer);
}
fclose(fp);
}
القراءة والكتابة الثنائية
عندما يكون من الضروري حفظ أو قراءة البيانات بصيغة غير نصية (مثل البنية struct)، يتم استخدام دوال fread() وfwrite():
cstruct Pessoa {
char nome[50];
int idade;
};
struct Pessoa p1 = {"Amine", 30};
FILE *fp = fopen("pessoa.bin", "wb");
fwrite(&p1, sizeof(struct Pessoa), 1, fp);
fclose(fp);
لقراءة من نفس الملف:
cstruct Pessoa p2;
fp = fopen("pessoa.bin", "rb");
fread(&p2, sizeof(struct Pessoa), 1, fp);
fclose(fp);
التعامل مع EOF والنهايات
عند التعامل مع الملفات أو الإدخال، قد يتم الوصول إلى نهاية الإدخال (EOF – End Of File). يمكن التحقق من ذلك باستخدام:
-
feof(FILE *): لاختبار نهاية الملف. -
ferror(FILE *): لاختبار حدوث خطأ في الملف. -
EOF: الثابت الذي يمثل نهاية الإدخال.
مثال:
cint ch;
while ((ch = getchar()) != EOF) {
putchar(ch);
}
الفرق بين دوال الإدخال والإخراج الأساسية
الجدول التالي يوضح مقارنة موجزة بين بعض دوال الإدخال والإخراج في لغة C:
| الدالة | نوع العملية | المستوى | السياق |
|---|---|---|---|
printf() |
إخراج | عالي | إلى الشاشة |
scanf() |
إدخال | عالي | من المستخدم |
getchar() |
إدخال | منخفض | من المستخدم |
putchar() |
إخراج | منخفض | إلى الشاشة |
fprintf() |
إخراج | عالي | إلى ملف |
fscanf() |
إدخال | عالي | من ملف |
fgets() |
إدخال | عالي | من ملف أو stdin |
fputs() |
إخراج | عالي | إلى ملف أو stdout |
fread() |
إدخال | منخفض | ثنائي |
fwrite() |
إخراج | منخفض | ثنائي |
الاعتبارات الأمنية والتنظيمية
-
التحقق من الأخطاء: يجب دائماً التحقق من فشل عمليات الإدخال والإخراج. استخدام قيم الإرجاع مثل
NULLأوEOFضروري لتفادي الأعطال. -
إدارة الذاكرة: تأكد من أن السلاسل النصية لديها حجم كافٍ لتخزين البيانات المدخلة.
-
الاعتمادية: استخدم دوال آمنة مثل
fgets()بدلاً منgets()لتفادي تجاوز حدود الذاكرة. -
إغلاق الملفات: أي ملف يُفتح بـ
fopen()يجب أن يُغلق بـfclose()لتجنب تسرب الموارد.
الخاتمة التقنية
تشكل عمليات الإدخال والإخراج حجر الزاوية في أي برنامج بلغة C، لما توفره من وسيلة لربط العالم الخارجي بالمنطق البرمجي الداخلي. عبر استخدام المكتبة ودوالها المتنوعة، يمكن تحقيق تفاعل مرن وقوي مع المستخدم والملفات، مما يجعل برنامج C قادراً على العمل بكفاءة في بيئات مختلفة. الفهم العميق لكيفية تنسيق البيانات والتمييز بين أنواع الإدخال والإخراج (النصي والثنائي، العالي والمنخفض المستوى) يمثل خطوة مهمة لأي مبرمج يسعى لبناء تطبيقات موثوقة وقابلة للتوسع.
المراجع:
-
Kernighan, B. W., & Ritchie, D. M. (1988). The C Programming Language (2nd ed.). Prentice Hall.
-
ISO/IEC 9899:2018 — Programming languages — C (C18 Standard).

